package generics;

import gui.Canvas;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;
import java.util.List;

/**
 * This abstract class represents a movable object to be animated in the
 * display. Movable object also belongs to a group (single movers can belong to
 * their a group with only themselves)
 * 
 * NOTE: We left the trail implementation in here but don't use it because it
 * might be useful in future, perhaps for debugging etc, but it was not really
 * for flocks.
 * 
 * @author Thomas Marmaduke, jianweigan
 * 
 */
public class AbstractMover extends AbstractSprite {

	private Point myVelocity;
	private int myMaxTrail;
	private List<Point> myTrail;

	public AbstractMover(Point center, Dimension size, Point velocity,
			Color color, String type, int trailSize) {
		super(center, size, color, type);
		myVelocity = new Point(velocity.x, velocity.y);
		myMaxTrail = trailSize;
		myTrail = new LinkedList<Point>();
		myTrail.add(new Point(center));
	}

	/**
	 * Describes how to "animate" the shape by changing its state.
	 * 
	 * @param bounds
	 *            which encloses this shape
	 */
	public void update(Canvas canvas) {
		getCenter().translate(myVelocity.x, myVelocity.y);
		myTrail.add(new Point(getCenter()));
		if (myTrail.size() >= myMaxTrail) {
			myTrail.remove(0);
		}
	}

	/**
	 * Describes how to draw the shape on the screen, includes implementation of
	 * drawing the trail of a mover.
	 * 
	 * Currently, draw a trail of the shape's previous positions if it exists.
	 * 
	 * @param pen
	 *            used to paint shape on the screen
	 */
	@Override
	public void paint(Graphics pen) {
		if (myMaxTrail > 0) {
			drawTrail(pen);
		}
	}

	/**
	 * Reports shape's velocity.
	 * 
	 * @return velocity of shape
	 */
	public Point getVelocity() {
		return myVelocity;
	}

	/**
	 * alters the center if the flock member travels offscreen so that it will
	 * appear on the display by adding/subtracting the height/width
	 * 
	 * @param screenDimension
	 */
	public void wrap(Dimension screenDimension) {
		getCenter().x = (getCenter().x + screenDimension.width)
				% screenDimension.width;
		getCenter().y = (getCenter().y + screenDimension.height)
				% screenDimension.height;
	}

	/**
	 * Draws a trail connecting the shape's previous positions.
	 * 
	 * @param pen
	 *            used to paint shape on the screen
	 */
	private void drawTrail(Graphics pen) {
		pen.setColor(getColor());
		// draw trail
		Point previous = myTrail.get(0);
		for (int k = 1; k < myTrail.size(); k++) {
			Point current = myTrail.get(k);
			pen.drawLine(previous.x, previous.y, current.x, current.y);
			previous = current;
		}
	}

}
